/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MyIM.server.engine;

import MyIM.client.callback.CallBackRemote;
import MyIM.component.Friend;
import MyIM.component.Group;
import MyIM.utilities.Constants;
import MyIM.utilities.Status;
import java.io.*;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

/**
 *
 * @author satthuvdh
 */
public class ServerEngine extends UnicastRemoteObject implements ServerModel {

    public static int RMIREGISTRY_PORT = 1099;
    public static String REMOTE_OBJECT_URL = "rmi://localhost:1099/ChatServer";
    private Connection conn;
    private final HashMap<Integer, CallBackRemote> users = new HashMap<>();

    public ServerEngine() throws RemoteException {
        try {
            LocateRegistry.createRegistry(RMIREGISTRY_PORT);
            Naming.rebind(REMOTE_OBJECT_URL, this);
            connectDatabase();
        } catch (MalformedURLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public CallBackRemote getCallBackRemoteById(int id) {
        return users.get(id);
    }

    @Override
    public Status registering(String username, String password, String displayName, File avatar) {
        try {
            if (conn.getAutoCommit() == true) {
                conn.setAutoCommit(false);
            }
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT COUNT(*) FROM sa_users WHERE username ='" + username + "'");
            while (rs.next()) {
                if (rs.getInt("COUNT(*)") != 0) {
                    return Status.USER_EXIST;
                } else {
                    FileInputStream inputStream = new FileInputStream(avatar);
                    PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO sa_users VALUES (null,?,?,?,?,false)");
                    preparedStatement.setString(1, username);
                    preparedStatement.setString(2, password);
                    preparedStatement.setString(3, displayName);
                    preparedStatement.setBinaryStream(4, inputStream, (int) (avatar.length()));
                    preparedStatement.executeUpdate();
                    conn.commit();
                    return Status.SUCCESS;
                }
            }
            statement.close();
        } catch (SQLException ex) {
            try {
                conn.rollback();
                return Status.SERVER_ERROR;
            } catch (SQLException ex2) {
                throw new RuntimeException(ex2);
            }
        } catch (FileNotFoundException ex) {
            return Status.SERVER_ERROR;
        } finally {
            try {
                conn.setAutoCommit(true);
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
        return Status.FAIL;
    }

    public final void connectDatabase() {
        try {
            Class.forName(Constants.CLASSNAME);

            if (Constants.USERNAME == null || Constants.USERNAME.equals("")) {
                conn = DriverManager.getConnection(Constants.CONNECTSTRING);
            } else {
                conn = DriverManager.getConnection(Constants.CONNECTSTRING, Constants.USERNAME, Constants.PASSWORD);
            }
        } catch (ClassNotFoundException | SQLException ex) {
            System.out.println(Status.CONNECT_DATABASE_FAIL + ex.toString());
        }
    }

    @Override
    public Status login(String username, String password, CallBackRemote callback) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            PreparedStatement preparedStatement = conn.prepareStatement("SELECT COUNT(*) AS ROWCOUNT FROM sa_users WHERE USERNAME = ? AND PASSWORD= ? ");
            preparedStatement.setString(1, username);
            preparedStatement.setString(2, password);
            ResultSet rs = preparedStatement.executeQuery();
            //statement.executeQuery("SELECT COUNT(*) AS ROWCOUNT FROM sa_users WHERE USERNAME ='" + username + "' AND PASSWORD='" + password + "'");
            System.out.println(username + " " + password);
            while (rs.next()) {
                if (rs.getInt("ROWCOUNT") != 1) {
                    return Status.WRONG_PASSWORD_OR_USERNAME;
                } else {
                    ResultSet rs1 = statement.executeQuery("SELECT uid FROM sa_users WHERE username ='" + username + "'");
                    synchronized (users) {
                        while (rs1.next()) {
                            users.put(rs1.getInt("uid"), callback);
                            return Status.SUCCESS;
                        }

                    }
                }
                statement.close();
            }
        } catch (SQLException ex) {
            return Status.SQL_ERROR;
        }
        return Status.SERVER_ERROR;
    }

    public void initUserInfomation(String username, CallBackRemote callback) {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs1 = statement.executeQuery("SELECT uid FROM sa_users WHERE username ='" + username + "'");

            while (rs1.next()) {
                sendOnlineNotify(rs1.getInt("uid"));
                //send offline message to the user
                addOffileMessage(rs1.getInt("uid"));
                conn.createStatement().executeUpdate("UPDATE sa_users SET status=1 WHERE username='" + username + "'");
            }

        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
    }

    @Override
    public void sendMessage(int from, int to, String message) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }

        h.get(from).addMessage(from, to, message);
        if (h.get(to) != null) {
            h.get(to).addMessage(from, to, message);

        } else {
            try {
                Statement statement = conn.createStatement();
                java.util.Date now = new java.util.Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
                String sdate = sdf.format(now).toString();
                statement.executeUpdate("INSERT INTO sa_offlines VALUES(null,'" + from + "','" + to + "','" + message + "','" + sdate + "','message')");
            } catch (SQLException ex) {
                Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
            }
        }


    }

    @Override
    public void logout(int uid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            if (users.remove(uid) != null) {
                try {
                    Statement statement = conn.createStatement();
                    statement.executeUpdate("UPDATE sa_users SET status='0' WHERE uid='" + uid + "'");
                } catch (SQLException ex) {
                    Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
                }
            }
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }

        String username = getUsernameById(uid);
        for (int user : h.keySet()) {
            h.get(user).friendOffline(uid);
        }
    }

    @Override
    public void changeGroup(int uid, int fid, int gid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            statement.executeUpdate("UPDATE sa_friends SET gid='" + gid + "' WHERE uid ='" + uid + "' AND fid='" + fid + "'");

            String username = getUsernameById(uid);
            h.get(uid).initFriendList(username);
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
    }

    @Override
    public int getIdFromUsername(String username) {
        try {
            Statement statement = conn.createStatement();

            ResultSet rs = statement.executeQuery("SELECT uid FROM sa_users WHERE username='" + username + "'");
            while (rs.next()) {
                return rs.getInt(1);
            }
        } catch (SQLException ex) {
            return -1;
        }
        return -1;
    }

    @Override
    public Status addFriend(int uid, int fid, int gid) throws RemoteException {
        try {
            Statement statement = conn.createStatement();

            statement.executeUpdate("INSERT INTO sa_friends(uid,fid,gid) VALUES('"
                    + uid + "','" + fid + "','" + gid + "')");
            return Status.SUCCESS;
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
    }

    @Override
    public Status removeFriend(int uid, int fid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            statement.executeUpdate("DELETE FROM sa_friends WHERE uid='" + uid + "' AND fid='" + fid + "'");
            String username = getUsernameById(uid);
            h.get(uid).initFriendList(username);
            return Status.SUCCESS;
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
    }

    private void addOffileMessage(int uid) {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT * FROM sa_offlines WHERE to_id ='" + uid + "'");
            while (rs.next()) {
                try {
                    if (rs.getString("type").compareTo("request") == 0) {
                        h.get(uid).requestAddFriend(rs.getInt("from_id"), rs.getInt("to_id"), Integer.parseInt(rs.getString("message")));

                    } else {
                        h.get(uid).addMessage(rs.getInt("from_id"), uid, rs.getString("message"));
                    }

                } catch (RemoteException ex) {
                    System.out.println(Status.REMORE_ERROR);
                }
            }
            statement.executeUpdate("DELETE FROM sa_offlines WHERE to_id='" + uid + "'");
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
    }

    @Override
    public ArrayList<Group> getFriendList(int uid) {
        ArrayList<Group> friend = new ArrayList<>();

        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT g.* FROM sa_groups g WHERE uid = '" + uid + "'");

            while (rs.next()) {
                int gId = rs.getInt(1);
                String gName = rs.getString(2);
                Group g = new Group(uid, gId, gName, new ArrayList<Friend>());
                addFriendToGroup(g, uid, gId);
                friend.add(g);
            }

            return friend;

        } catch (SQLException ex) {

            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
        return null;

    }

    private void addFriendToGroup(Group g, int uid, int gid) {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs2 = statement.executeQuery("SELECT u.uid, u.username, u.display, u.avatar, u.status"
                    + " FROM sa_users u, sa_friends f WHERE f.uid = '" + uid + "' AND u.uid = f.fid"
                    + " AND f.gid='" + gid + "'");
            while (rs2.next()) {
                int fId = rs2.getInt(1);

                String fUsername = rs2.getString(2);

                String fDisplay = rs2.getString(3);
                InputStream binaryStream = rs2.getBinaryStream(4);
                ImageIcon image = new ImageIcon(ImageIO.read(binaryStream));
                boolean fStatus = rs2.getBoolean(5);
                g.addFriend(new Friend(fId, fUsername, fDisplay, fStatus, image));
            }
        } catch (IOException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
    }

    @Override
    public Status checkUserExists(String username) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT COUNT(*) FROM USERS WHERE USERNAME ='" + username + "'");
            while (rs.next()) {
                if (rs.getInt(1) == 1) {
                    return Status.USER_EXIST;
                } else {
                    return Status.USER_NOT_EXIST;
                }
            }
        } catch (SQLException ex) {
            return Status.SQL_ERROR;
        }
        return Status.FAIL;
    }

    @Override
    public void sendMessageConf(int ownerid, String confereceName, int from, ArrayList<Friend> to, String message) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        for (Friend friend : to) {

            h.get(friend.getUid()).addMessageConference(ownerid, confereceName, from, message);

        }

    }

    @Override
    public Status addGroup(String groupName, int uid) {
        try {
            if (conn.getAutoCommit() == true) {
                conn.setAutoCommit(false);
            }
            Statement statement = conn.createStatement();
            PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO sa_groups(groupname,uid) VALUES (?,?)");
            preparedStatement.setString(1, groupName);
            preparedStatement.setInt(2, uid);
            preparedStatement.executeUpdate();
            conn.commit();
            //return Status.SUCCESS;
            statement.close();
            return Status.SUCCESS;
        } catch (SQLException ex) {
            try {
                conn.rollback();
                return Status.SERVER_ERROR;
            } catch (SQLException ex2) {
                throw new RuntimeException(ex2);
            }
        } finally {
            try {
                conn.setAutoCommit(true);
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
        }
    }
//    private void initFriend(CallBackRemote callback, String username) {
//        try {
//            Statement statement = conn.createStatement();
//            ResultSet rs2 = statement.executeQuery("SELECT * FROM USERS WHERE USERNAME ='" + username + "'");
//            while (rs2.next()) {
//                InputStream binaryStream = rs2.getBinaryStream(3);
//                ImageIcon image = new ImageIcon(ImageIO.read(binaryStream));
////                callback.initUser(username, rs2.getString("DISPLAYNAME"), image);
//            }
//        } catch (IOException | SQLException ex) {
//            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
//        }
//    }

    @Override
    public int getGroupIdByName(String groupName, int uid) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs2 = statement.executeQuery("SELECT * FROM sa_groups WHERE groupname ='" + groupName + "' AND uid='" + uid + "'");
            while (rs2.next()) {
                return rs2.getInt(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return -1;
    }

    @Override
    public Group getGroupByName(String groupName, int uid) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs2 = statement.executeQuery("SELECT * FROM sa_groups WHERE groupname ='" + groupName + "' AND uid='" + uid + "'");
            while (rs2.next()) {
                return new Group(rs2.getInt(3), rs2.getInt(1), rs2.getString(2), new ArrayList<Friend>());
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    @Override
    public String getDisplayName(String username) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT display FROM sa_users WHERE username='" + username + "'");
            while (rs.next()) {
                return rs.getString(1);
            }
        } catch (SQLException ex) {
            return Status.SQL_ERROR.toString();
        }
        return Status.FAIL.toString();
    }

    @Override
    public ImageIcon getAvatar(String username) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT avatar FROM sa_users WHERE username='" + username + "'");
            while (rs.next()) {
                InputStream binaryStream = rs.getBinaryStream(1);
                ImageIcon image = new ImageIcon(ImageIO.read(binaryStream));
                return image;
            }
        } catch (IOException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        }
        return null;
    }

    private void sendOnlineNotify(int uid) {

        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT uid FROM sa_friends WHERE fid='" + uid + "'");
            while (rs.next()) {
                System.out.println(rs.getInt("uid"));
                if (h.containsKey(rs.getInt("uid"))) {
                    System.out.println("Send message to id:" + rs.getInt("uid"));
                    h.get(rs.getInt("uid")).friendOnline(uid);
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, "SQL_ERROR", ex);
        } catch (RemoteException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    @Override
    public Status sendAddFriendRequest(int uid, int fid, int gid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT COUNT(*) FROM sa_friends WHERE fid='" + fid + "' AND uid='" + uid + "'");
            while (rs.next()) {
                if (rs.getInt(1) != 0) {
                    return Status.USER_EXIST;
                } else if (!h.containsKey(fid)) {
                    try {
                        java.util.Date now = new java.util.Date();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
                        String sdate = sdf.format(now).toString();
                        Statement statement1 = conn.createStatement();
                        statement1.executeUpdate("INSERT INTO sa_offlines(from_id,to_id,message,sendtime,type) "
                                + "VALUES ('" + uid + "','" + fid + "','" + gid + "','" + sdate + "', 'request')");
                        statement1.close();
                        return Status.SUCCESS;
                    } catch (SQLException ex) {
                        Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
                        return Status.SQL_ERROR;
                    }
                } else {
                    //server send request to friend
                    h.get(fid).requestAddFriend(uid, fid, gid);
                    return Status.SUCCESS;
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
        return Status.FAIL;
    }

    @Override
    public Status acceptAddFriend(int requested, int requester) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        if (h.containsKey(requester)) {
            String requestedUsername = getUsernameById(requested);
            if (requestedUsername != null) {
                h.get(requester).acceptAddFriend(requestedUsername);
            }
        }

        return Status.SUCCESS;
    }

    @Override
    public String getUsernameById(int id) throws RemoteException {
        try {
            Statement statement = conn.createStatement();

            ResultSet rs = statement.executeQuery("SELECT username FROM sa_users WHERE uid='" + id + "'");
            while (rs.next()) {
                return rs.getString(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
        return null;
    }

    @Override
    public Friend getFriend(int uid) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT * FROM sa_users WHERE uid='" + uid + "'");
            while (rs.next()) {
                InputStream binaryStream = rs.getBinaryStream("avatar");
                ImageIcon image = new ImageIcon(ImageIO.read(binaryStream));
                return new Friend(uid, rs.getString("username"), rs.getString("display"), rs.getBoolean("status"), image);
            }
        } catch (IOException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    @Override
    public Status removeGroup(int uid, int gid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            String username = getUsernameById(uid);
            statement.executeUpdate("DELETE FROM sa_groups WHERE gid='" + gid + "'");
            statement.executeUpdate("DELETE FROM sa_friends WHERE uid='" + uid + "' AND gid='" + gid + "'");
            h.get(uid).initFriendList(username);
            return Status.SUCCESS;
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
    }

    @Override
    public Status renameGroup(int uid, int gid, String text) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            String username = getUsernameById(uid);
            statement.executeUpdate("UPDATE sa_groups SET groupname = '" + text + "' WHERE gid='" + gid + "' AND uid='" + uid + "'");
            h.get(uid).initFriendList(username);
            return Status.SUCCESS;
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
    }

    @Override
    public Status moveFriend(int uid, int fid, int gid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        try {
            Statement statement = conn.createStatement();
            String username = getUsernameById(uid);
            statement.executeUpdate("UPDATE sa_friends SET gid = '" + gid + "' WHERE uid='" + uid + "' AND fid='" + fid + "'");
            h.get(uid).initFriendList(username);
            return Status.SUCCESS;
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            return Status.SQL_ERROR;
        }
    }

    @Override
    public Status inviteConference(int ownerid, String conferenceName, ArrayList<Friend> attendees, int uid) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }

        if (h.containsKey(uid)) {
            Status status = h.get(uid).addToConferene(ownerid, conferenceName, attendees);
            if (status == Status.SUCCESS) {
                attendees.add(getFriend(uid));
                initConference(h, ownerid, conferenceName, attendees);
            }
            return status;
        } else {
            return Status.USER_OFFLINE;
        }
    }

    private void initConference(HashMap<Integer, CallBackRemote> h, int ownerid, String conferenceName, ArrayList<Friend> attendees) {
        for (Friend friend : attendees) {
            try {
                h.get(friend.getUid()).initConference(ownerid, conferenceName, attendees);
            } catch (RemoteException ex) {
                Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    @Override
    public void exitConference(int ownerid, String conferenceName, ArrayList<Friend> attendees) throws RemoteException {
        HashMap<Integer, CallBackRemote> h;
        synchronized (users) {
            h = (HashMap<Integer, CallBackRemote>) users.clone();
        }
        for (Friend friend : attendees) {
            h.get(friend.getUid()).initConference(ownerid, conferenceName, attendees);
        }
    }

    @Override
    public void changeDisplay(int uid, String displayName) {
        try {
            Statement statement = conn.createStatement();
            statement.executeUpdate("UPDATE sa_users SET display='" + displayName + "' WHERE uid='" + uid + "'");
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void changeAvatar(int uid, File avatar) throws RemoteException {
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(avatar);
            PreparedStatement preparedStatement = conn.prepareStatement("UPDATE sa_users SET avatar=? WHERE uid='" + uid + "'");
            preparedStatement.setBinaryStream(1, inputStream, (int) (avatar.length()));
            preparedStatement.executeUpdate();
        } catch (SQLException | FileNotFoundException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                inputStream.close();
            } catch (IOException ex) {
                Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

    }

    @Override
    public void changePassword(int uid, String password) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            statement.executeUpdate("UPDATE sa_users SET password='" + password + "' WHERE uid='" + uid + "'");
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public String getPassword(int uid) throws RemoteException {
        try {
            Statement statement = conn.createStatement();
            ResultSet rs = statement.executeQuery("SELECT password FROM sa_users WHERE uid='" + uid + "'");
            while (rs.next()) {
                return rs.getString("password");
            }
        } catch (SQLException ex) {
            Logger.getLogger(ServerEngine.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}
